package net.pulseproject.router.modules.logic.beatstabilizer.old.approach2;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.pulseproject.router.modules.useable.BeatStabilizerModule;

public class OLD2_BeatTimeManager {
	
	private static final Log LOG = LogFactory.getLog(OLD2_BeatTimeManager.class);
	
	private final OLD2_BeatHistory history;

	private final long globalMinMs;
	private final int globalMaxMs;
	
	private final double frameDeviationPercent; // input from user, actually not used. e.g.: "2.5D"
	private final double frameDeviationPercentBy100; // e.g.: "0.025"
	private final double frameDeviationMaxPercent; // precalculated ready2use max multiplicator: e.g.: "1.025D"
	private final double frameDeviationMinPercent; // precalculated ready2use min multiplicator: e.g.: "0.075D"

	public OLD2_BeatTimeManager(OLD2_BeatHistory history, long globalMinMs, int globalMaxMs, double frameDeviationPercent) {
		if(globalMinMs > globalMaxMs) {
			throw new IllegalArgumentException("globalMinMs > globalMaxMs");
		}
		
		this.history = history;
		this.globalMinMs = globalMinMs;
		this.globalMaxMs = globalMaxMs;
		this.frameDeviationPercent = frameDeviationPercent;
		
		this.frameDeviationPercentBy100 = frameDeviationPercent / 100.0D;
		this.frameDeviationMaxPercent = 1.0D + this.frameDeviationPercentBy100;
		this.frameDeviationMinPercent = 1.0D - this.frameDeviationPercentBy100;
	}

	public long calcTimeframeDelayByOwnVelocity(long timestampLastMessageSent) {
		LOG.trace("calcTimeframeDelayByOwnVelocity(timestampLastMessageSent="+timestampLastMessageSent+")");
		if(timestampLastMessageSent == -1) {
			LOG.trace("returning global max, as not any data (neither history, nor own velocity) was available");
			return this.globalMaxMs;
		}

		return this.multipleWithMaxFrameDeviationAndLimitByGlobalMax(timestampLastMessageSent);
	}

	public long calcTimeframeDelayByHistory() {
		LOG.trace("calcTimeframeDelayByHistory()");
		
		long realBeatAverageDuration = this.history.calcAverageDuration();
		if(realBeatAverageDuration == OLD2_BeatHistory.NOT_ENOUGH_DATA) {
			return OLD2_BeatHistory.NOT_ENOUGH_DATA;
		}
		return this.multipleWithMaxFrameDeviationAndLimitByGlobalMax(realBeatAverageDuration);
	}
	
	private long multipleWithMaxFrameDeviationAndLimitByGlobalMax(double delayToBeMultiplied) {
		long delay = Math.round(delayToBeMultiplied * this.frameDeviationMaxPercent);
		long result = Math.min(this.globalMaxMs, delay);
		LOG.trace("multipleWithMaxFrameDeviationAndLimitByGlobalMax(delayToBeMultiplied=" + delayToBeMultiplied + ") ... result=" + result);
		return result;
	}
}
